#PRAGMA array_base = 1 
#PRAGMA explicit = true
'todas las definicios automaticas generadas al general los bloques binarios y que _
'coinciden con la ubicaciones en los mismos
'****************************************************************
'             COMPOSICION BUFFER DE MEMORIA PANTALLA
'****************************************************************
/'ADR_SCREEN_TILE_MAP
    768  screen tiles
    96   bitmap extension paleta (lleva la cantidad de tiles a 504)
    768
    96   union bitmap layer (fusion of all the active layers for the active screen)
   873   ( 9 layers of 96 bytes + 1 byte y of the layer.)
   121   buffer screen limits
  2722      total 
    96   adicionales bitmap vacio para insertar en unionLayer
'/ 
'****************************************************************
'                ACTIVA Y DESACTIVA COSAS
'****************************************************************
#DEFINE SONIDO_ACTIVADO
'el release debe tener comentada ramdrive, si esta definida el progra
'ma trabaja con el ramdrive.Si esta comentada trabaja cargando bloques
'comunes
'#DEFINE RAMDRIVE
#INCLUDE "./constants.txt"
#INCLUDE "./defBlock1.txt"
#INCLUDE "./defBlock4.txt"
#INCLUDE "./defBlock6.txt"
'****************************************************************
'                VARIABLES GLOBALES Y COMUNES
'****************************************************************

'defino variable Comunes al programa compilado en la 24576 y la 49152, _ 
' llamador y llamado respectivamente.
#IFDEF SONIDO_ACTIVADO
    #INCLUDE "./musica/defVarComunesMusica.bas"
#ENDIF
DIM test AS UBYTE = 0
'menu option
dim choice as ubyte



DIM xOld(8) AS UBYTE =>{ 100,100,100,100,100,100,100,100}
DIM xOldFinal(8) AS UBYTE =>{ 100,100,100,100,100,100,100,100}
dim TiempoFinalJuego as ulong
dim statusDeliveryBurbuja as ubyte
dim TimerBurbujaDelivery as long


'DIM borraDelanteDelSprite AS UBYTE = 1 
'cuando esta en 1 se reimprime background delante del sprite

DIM timers(4)  AS ubyte 'array de timers del juego
timers(1) = 0 'timer movimientos mc
timers(2) = 0 'eyes main caracter
timers(3) = 0 'mouth main caracter
timers(4) = 0 'musica


DIM pantallaActiva AS UBYTE = 1
'cantidad de capas de la pantalla donde esta el personaje ahora
DIM CantLayersActiveScreen AS UBYTE
DIM AdrInicioCapasActiveScreen AS UINTEGER
DIM AdrPaletteExtension As UINTEGER
DIM AdrUnionLayer AS UINTEGER
DIM AdrScreenObjectsTileMap AS UINTEGER
dim AdrScreenLimits as uinteger

AdrPaletteExtension           = ADR_SCREEN_TILE_MAP +768
AdrScreenObjectsTileMap       = AdrPaletteExtension+96
AdrUnionLayer                 = AdrScreenObjectsTileMap +768
AdrInicioCapasActiveScreen    = AdrUnionLayer+96
AdrScreenLimits               = AdrInicioCapasActiveScreen + 873      '9 layer * 96



DIM temp AS BYTE = 0
DIM oS AS BYTE = 0  'offset , sirve para agregar un offset a los sprites

'datos posicionales
/'  coorSprites
define ocho filas de tres atributos (una fila por cada linea del sprite). 
1 atributo: ColumnCaracterDesde. A partir de  X cuantos caracteres tiene que estar desplazada la linea(para que coincidan las distintas lineas del sprite)
2 atributo: longitud en caracteres de la linea en la que estoy 
3 atributo: longitud en caracteres de la linea anterior a la que estoy , acumulativo, va acumulando el numero linea a linea
'/
DIM coorSprites(8,3) AS UBYTE
DIM caracteresMapa(25,2) AS BYTE

DIM xp, yp as BYTE 
'if GameStatus = 0 game on, 1 game end for time, 2 for objects
dim GameStatus as ubyte
' if alreadyPlayedIntro = 1 the intro has already been played
dim alreadyPlayedIntro as ubyte
'x e y de la pantalla . Si elegimos xp =0 , yp =0 entonces corresponde a la pantalla 0. El x y el y definen la pantalla
dim textMessage as string
textMessage = "                                "

'dim textAdr as uinteger
xp =0
yp = 0

'DIM initialScreenAddress AS UINTEGER
    
'contiene las distintas capas de cada habitacion del juego
'#INCLUDE "./mapas/capa.bas"

'contiene los graficos individuales para componer cada habitacion del juego


'****************************************************************
'               INCLUDES DE BIBLIOTECAS
'****************************************************************
DECLARE FUNCTION LeerTecla AS UInteger


#INCLUDE <printfzx.bas>
#INCLUDE <scrbuffer.bas>               
#INCLUDE "./variablesMc.bas"
#INCLUDE <memcopy.bas>
#INCLUDE <putchars.bas>
#INCLUDE <retrace.bas>
#INCLUDE <keys.bas>

' Guardaremos los códigos de las teclas en un array
DIM Teclas(10) AS UInteger
    
DIM keyAsciiCodes(10) AS STRING 
    
' array of key labels
DIM TeclasS(10) AS String
dim sinclairPort as ubyte
dim sinclairString as string


' Tipo de control, 1=Teclado, 2=KEMPSTON,
'   3=SINCLAIR 1, 4=SINCLAIR 2, 5=CURSOR 
DIM TipoControl AS UByte = 1

#INCLUDE "./functions.bas"
#INCLUDE "./functionsScreen.bas"
#INCLUDE "./functionsMc.bas"
#INCLUDE <zx0.bas>
#INCLUDE "./intro.bas"   






'****************************************************************
'               INICIO EJECUCION DE CODIGO
'****************************************************************

changeToStandardKeys()



'key names 
TeclasS(IZQUIERDA) = " LEFT "
TeclasS(DERECHA)   = " RIGHT "
TeclasS(ARRIBA)    = " UP  "
TeclasS(ABAJO)     = "  DOWN  "
TeclasS(INTERAC)   = "GRAB PUT"
TeclasS(SOLTAR)   = "DROP     "
TeclasS(INFO)   = "INFO "
TeclasS(REPM)   = "REP. MUSIC"
TeclasS(STOPM)   = "STOP MUSIC"
TeclasS(PAUSEM)   = "PAUSE MUSIC"

#IFDEF RAMDRIVE
    PRINT "CARGAR DATOS GRAFICOS"
    SetSlot3(4)
    PAUSE 0
    copiaDatosDeUnBancoAOtro(4, 0)  

    PRINT "CARGAR MAPA"
    SetSlot3(1)
    PAUSE 0
    SetSlot3(0)
    #IFDEF SONIDO_ACTIVADO
      PRINT "CARGAR DATOS MUSICA"
      SetSlot3(6)
      PAUSE 0
    #ENDIF
    
    
#ELSE
    load "" code
    
    SetSlot3(1)
    load "" code
    SetSlot3(6)
    load "" code
    
#ENDIF


/'
define la direccion de Memoria donde esta la melodia a reproducir. Para 
determinar cual es hay que iniciar en la 49512 ( inicio slot 3) y sumarle la
duracion del reproductor. La cual va a estar dada por exeBank6.bin. Eso da la
direccion donde comienza la melodia, es decir RepAyAddress
'/
/'
la direccion con debuger es 53696 y sin 50822     

'/
#IFDEF SONIDO_ACTIVADO
    RepAyAddress = song1
    'tipo de reproduccion: 0 una vez ,1 reproduccion continua
    tipoRepAy = 1
    'arranque con la reproduccion parada.
    statusRepAy = 2
    'inicializa chip, volumen, melodia y muestra info
    'valor inicial reproduccion parada
    ejecutaSonidoAy(inicializa_chip_melodia_muestra_info)
    SetSlot3(0)
#ENDIF
'define los nombres para las teclas



BORDER 0

 
dzx0Turbo(PARTUZA_IMG,$4000)



ejecutaSonidoAy(reproductor_en_play)  
DO WHILE  INKEY = "" 
   ejecutaSonidoAy(procesa_una_nota)
Loop


printFzxSetFontAddr(hemery_font)


do
    choice = loadMenu()
   
     if choice = 0 then
        cls
       
        printFzxSetFontAddr(font1)
        refreshScreen()
        if alreadyPlayedIntro = 0 then
            intro()
        end if
        border 2
        
        buclePrincipalJuego
     else if choice =1 then
          cls
          RedefinirTeclas()
     else if choice = 2 then
          sinclairPort = 0
     else if choice = 3 then
          sinclairPort = 0
     else if choice = 4 then
         if sinclairPort = 0 then
            sinclairPort = 1
         else if sinclairPort = 1 then
            sinclairPort = 2
         else if sinclairPort = 2 then
            sinclairPort = 1
         end if
         changeToSinclair()
     else if choice = 5 then
          sinclairPort = 0
          changeToCursor()
     else if choice = 6 then
        cls
        refreshScreen()
        printFzxSetFontAddr(font1)
        credits()
     end if
     'back to the menu's font
     printFzxSetFontAddr(hemery_font)
loop

sub buclePrincipalJuego()
 resetVariables()
 
cls
'ACA PARA PROBAR CODIGO

inputT()
if not GameStatus then
    cargaPantalla(0)
end if
SetSlot3(6)
RepAyAddress = song1 
 SetSlot3(0)
 ejecutaSonidoAy(reproductor_en_play)
DO        
         #IFDEF SONIDO_ACTIVADO
            
            ejecutaSonidoAy(procesa_una_nota)
       
         #ENDIF
         imprimeSpritesEnPantalla()  
          
         
         #IFDEF SONIDO_ACTIVADO
            
            ejecutaSonidoAy(procesa_una_nota)
       
         #ENDIF
         
         inputMc()
         /'if the argument of checkForGameEnd is 1 , its check for object
         completion and then for time, if the argument es 0 it only checks
         for time
         '/
         if GameStatus = 0 then
          GameStatus = checkForGameEnd(0) 
         end if
         if GameStatus then
            endGame(GameStatus)  
             exit do   
         end if
         'check if the purchase of burbuja has already happen
         if statusDeliveryBurbuja then
           if checkTimeForBurbujaDelivery()
              poke OBJ_MAP_HEADER +31,1
              drawScreenObjects()
              'the variable statusDeliveryBurbuja served its purpouse , so I put it again in 0
              'to avoid OBJ_MAP_HEADER +31,1 to run repetealy
              statusDeliveryBurbuja =0
           end if
         end if
        
               
        
        
        musicInput()
            
        
LOOP 

end sub

'modo 0 es el normal , modo 1 cambia el codigo para la intro
SUB cargaPantalla(modo as ubyte)
/' Las pantallas se dibujan en tiled, y un script de python transforma el mapa que genera tiled en un bloque de datos donde cada pantalla tiene un x,y para indentificarla dentro del mapa. El script va volcando las pantallas al bloque de datos y ubicandolas desde la esquina superior izquierda del mapa , avanzando hacia la derecha y al terminar la linea , pasando abajo al extremo izquierdo, asi hasta terminal el mapa, con ese orden quedan en el archivo. Pongo un ejemplo donde cada pantalla esta representada entre parentesis (). Esta seria la estructura del bloque y la ubicacion de cada pantalla, para un mapa de 9 pantallas ubicadas en tres lineas de tres pantallas por linea.
(y = -1, x = -1), (y = -1, x = 0) ,(y = -1,x = 1)
(y = 0, x = -1), (y = 0, x = 0) ,(y = 0,x = 1)
(y = 1, x = -1), (y = 1, x = 0) ,(y = 1,x = 1)

Donde lo que define la pantalla central x,y = 0 , es la primera pantalla que se comienza a dibujar en tiled.
Entonces en el bloque tenemos la siguiente estructura
El inicio del bloque esta en la direccion map_header que es la direccion de comienzo del bloque de pantallas, en este header estan representadas todas las pantallas en bloques de 4 bytes por pantalla donde 
valorX: Byte unsigned. Esta posicion contiene el valor x de la pantalla dentro del mapa. O sea que los valores x van de -127 a 128
valorY: Byte unsigned.  Esta posicion contiene el valor y de la pantalla dentro del mapa. Idem  para los valores y
offset pantalla : word. Contiene el offset necesario para sumar a start_map que nos da la direccion en memoria de la pantalla con el x, y de los bytes anteriores
Luego de este header que tendra la longitud de n pantallas x 4, viene start_map donde es el comienzo de las pantallas propiamente dichas, las cuales se encuentran una detras de la otra en el orden anteriormente descripto
'/
   
  
  DIM tilePosition AS UINTEGER   
  DIM tipoProcScreen AS BYTE
  DIM offset AS UINTEGER
  DIM n, r as ubyte
  's  AS UBYTE  
  'DIM t AS UINTEGER
  DIM valueTileScreen AS UBYTE
  DIM tileScreenOffset AS UINTEGER
  'dim adrLayer as uinteger
  dim offsetScreenLimitBlock as uinteger 
  dim h as ubyte
   'avoid showing garbage in the screen during copying
   for h = 0 to 8
    cambiaAtributoLineaTexto(16384,h,0)
   next h
  
  'vuelca la pantalla activa
  tipoProcScreen =1
  SetSlot3(1)   
  MemCopy(start_map + findScreenBlock(map_header,start_map,tipoProcScreen) _
  ,16384,864)
  SetSlot3(0)       
  MemCopy(16384,ADR_SCREEN_TILE_MAP,864)  '48128
  'clean objectsTileMaps, Layers and Limits
  cleanMapArtefacts()
     
    
  
  'vuelca las capas de la pantalla activa
  tipoProcScreen = 2
  SetSlot3(1)
  offset   = findScreenBlock(layer_header,start_layer,tipoProcScreen)
  IF tipoProcScreen >= 0 then
      CantLayersActiveScreen  = tipoProcScreen
      MemCopy(start_layer + offset ,16384,CAST(UINTEGER,CantLayersActiveScreen)*97)
      SetSlot3(0)       
      MemCopy(16384,AdrInicioCapasActiveScreen,CAST(UINTEGER,CantLayersActiveScreen)*97)
      
      
  ELSE 
    /'
    si tipoProcScreen retorno con -1 significa que no encontro ninguna layer
    layer para esa screen, por lo que pongo la cantidad de layers en 0,
    lo que indica a la funcion sinMascara que directamente no necesita
    chequear
    '/
      CantLayersActiveScreen = 0
      SetSlot3(0)
  END IF
    
    
    
    
    'get the active screen limits
    SetSlot3(1)  
  tipoProcScreen =1
  offsetScreenLimitBlock = findScreenBlock(LIMITS_HEADER,LIMITS_START,tipoProcScreen)
  
  
  MemCopy(LIMITS_START+ offsetScreenLimitBlock,16384,121)
  SetSlot3(0)
  MemCopy(16384,AdrScreenLimits,121)
  
  
   
     
    'muestra la pantalla normal para pintar la pantalla, en este caso no me preocupa el parpadeo o defectos y dibujarlo en la pantalla normal acelera el proceso que sino es muy lento
    if modo = 0 then
      switch2NormalScreenSWR()
    end if
    
    tilePosition = 1
    FOR n = 0 TO 23
       
     
    /'
    en intervalos regulares trata de tocar una nota para que la melodia no
    se altere al pasar de una pantalla a la otra porque demasiado tiempo 
    hasta que se vuelve a chequear la duracion de las notas, se nota en
    notas cortas
    '/
    
    
    #IFDEF SONIDO_ACTIVADO    
         
         ejecutaSonidoAy(procesa_una_nota)
         
    #ENDIF
    
     FOR r = 0 TO 31
        /'
        busca en el mapa de 768 bytes que compone la pantalla, la posicion
        de paleta del byte a pintar
        '/
        valueTileScreen = peek(ADR_SCREEN_TILE_MAP+tilePosition-1)      
        /'  
        busca en la paleta la posicion que corresponde al dibujo que va en 
        el byte a pintar
        '/
        tileScreenOffset = (CAST(UINTEGER,valueTileScreen) -1)*8
        'se fija de que paleta tiene que buscar el tile
        IF devuelveValorPosicionBitMap(tilePosition, AdrPaletteExtension) > 0 then
         putChars(r, n ,1,1,paletaB_s + tileScreenOffset)
         PaintData(r,n ,1,1,paletaB_a+ CAST(UINTEGER,valueTileScreen)-1 )  
        ELSE
         IF valueTileScreen = 1 then
          PaintData(r,n ,1,1,paletaA_a + CAST(UINTEGER,valueTileScreen)-1 )
         ELSE
          putChars(r,n ,1,1,paletaA_s + tileScreenOffset)
          PaintData(r,n ,1,1,paletaA_a+ CAST(UINTEGER,valueTileScreen) -1)  
         END IF
        END IF

        
        tilePosition = tilePosition +1
     NEXT r 
    NEXT n
    
    
    if modo = 0 then
      drawScreenObjects()
    end if
    
    buidUnionLayer()
    
    
    'imprimeCuadricula()
    'copia el screen a la shadow y a partir de ahi trabaja con la shadow. Pero visualmente se gana mucho tiempo ya que se puede ver
    'la pantalla dibujada desde que comienza a pintar el screen normal
    if modo = 0 then
        SetSlot3(7)
        MemCopy(16384,49152,6912)
        SetSlot3(0)
        switch2ShadowScreenSWR()
    end if
END SUB

SUB imprimeSpritesEnPantalla()
    printMc(0)    
    
END SUB
    
'ejecuta comando o set comandos en bank.bas usando la variable variableComun1 para trasladar mi requerimiento.
#IFDEF SONIDO_ACTIVADO
    SUB ejecutaSonidoAy(comando as UBYTE)
        SetSlot3(6) 
        variableComun1 = comando
        RANDOMIZE usr ubicacion_reproductor
        SetSlot3(0)
    END SUB
    SUB ejecutaSonidoAyWithoutCbank(comando as UBYTE)     
        variableComun1 = comando
        RANDOMIZE usr ubicacion_reproductor   
    END SUB  
#ENDIF



